package org.jchains.receiver.gui;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JTable;

import javax.swing.border.Border;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

class MyPermissionsRender extends JLabel implements TableCellRenderer {

	boolean isBordered = false;
	Border unselBorder = null;
	Border selBorder = null;

	public MyPermissionsRender(boolean _isBordered) {
		this.isBordered = _isBordered;
		setOpaque(true);
	}

	@Override
	public Component getTableCellRendererComponent(JTable table, Object value,
			boolean isSelected, boolean hasFocus, int row, int column) {

		String curval = (String) table.getModel().getValueAt(row, column);
		String type = (String) table.getModel().getValueAt(row, 2);

		Color normalback = table.getBackground();
		Color normalfore = table.getForeground();
		

		if (type.endsWith("FilePermission")) {
			normalback = Color.lightGray;
		}
		
		if (type.endsWith("PropertyPermission")) {
			normalback= Color.blue.brighter().brighter().brighter().brighter();
			normalfore= Color.white;
		}
		
		if (type.endsWith("RuntimePermission")) {
			normalback= Color.yellow;
		}
		
		if (type.startsWith("javax.security") ||  type.startsWith("java.security")) {
			normalback= Color.red;
			normalfore= Color.white;
		}

		if (type.startsWith("javax.management"))  {
			normalfore= Color.magenta;
		}


		setBackground(normalback);
		setForeground(normalfore);
		

		setText(curval);
		if (isBordered) {
			if (isSelected) {
				if (selBorder == null) {
					// selBorder = BorderFactory.createMatteBorder(1,4,1,4,
					// table.getSelectionBackground());
					selBorder = BorderFactory.createMatteBorder(1, 4, 1, 4,
							Color.RED);
				}
				setBorder(selBorder);
			} else {
				if (unselBorder == null) {
					unselBorder = BorderFactory.createMatteBorder(1, 4, 1, 4,
							table.getBackground());
				}
				setBorder(unselBorder);
			}
		}

		setToolTipText(curval );

		return this;
	}

}

public class PermissionsTable extends JTable {

	static class FilterableTableModel extends AbstractTableModel {

		private static final long serialVersionUID = 1L;

		TableModel delegateTableModel;
		int[] filterMapping;

		public FilterableTableModel(TableModel delegateTableModel) {
			this.delegateTableModel = delegateTableModel;
		}

		public int getRowCount() {
			return this.filterMapping != null ? this.filterMapping.length : 0;
		}

		public int getColumnCount() {
			return delegateTableModel.getColumnCount();
		}

		public Object getValueAt(int rowIndex, int columnIndex) {
			if (filterMapping.length > rowIndex) {
				//System.out.println(rowIndex + ":"	+ this.filterMapping[rowIndex]);
				return delegateTableModel.getValueAt(
						this.filterMapping[rowIndex], columnIndex);
			} else {
				// System.out.println("table too small");
				return "";
			}
		}

		public int[] getFilterMapping() {
			return filterMapping;
		}

		public void setFilterMapping(int[] filterMapping) {
			this.filterMapping = filterMapping;
		}

		public TableModel getDelegateTableModel() {
			return delegateTableModel;
		}

		public void setDelegateTableModel(TableModel delegate) {
			this.delegateTableModel = delegate;
		}

		public void removeRow(int idx) {
			if (delegateTableModel instanceof DefaultTableModel) {
				((DefaultTableModel) delegateTableModel)
						.removeRow(filterMapping[idx]);

			} else {
				throw new UnsupportedOperationException();
			}
		}
	}

	TableRowSorter<PermTableModel> sorter;

	String filter;
	FilterableTableModel filterableTableModel;
	int filterColumn = 3;

	int currentFilterMatches;
	int[] currentFilterMapping;

	static String[] strTooltips = {
			"The time the event occurred",
			"The codebase that required the permission",
			"The permission that was requested",
			"The privileged resource",
			"The action on the privileged resource",
			"The class in which the privileged access occurred",
			"The method in with the privileged access occurred",
			"The line in which the privileged access occurred (requires linenumbertable attribute)" };

	private static final long serialVersionUID = 1L;

	static MyPermissionsRender MyP = new MyPermissionsRender(true);

	public TableCellRenderer getCellRenderer(int row, int column) {
		return MyP;
	}

	public PermissionsTable() {
		super();
		PermTableModel ptm = new PermTableModel();
		setModel(ptm);
		filterableTableModel = new FilterableTableModel(ptm);

		// ptm.setTable(this);

		setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

		int[] colwidth = { 100, 250, 250, 350, 100, 250, 250, 100 };

		for (int i = 0; i < colwidth.length; i++) {
			TableColumn col = getColumnModel().getColumn(i);
			col.setPreferredWidth(colwidth[i]);
		}
		this.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
		this.setFillsViewportHeight(true);
		this.setAutoCreateRowSorter(true);

		sorter = new TableRowSorter<PermTableModel>(ptm);
		setRowSorter(sorter);

		/*
		 * getSelectionModel().addListSelectionListener(new
		 * ListSelectionListener() {
		 * 
		 * @Override public void valueChanged(ListSelectionEvent e) { // TODO
		 * Auto-generated method stub int viewRow = getSelectedRow(); if
		 * (viewRow < 0) {
		 * 
		 * } else { int modelRow = convertRowIndexToModel(viewRow);
		 * System.out.println(viewRow+":"+modelRow); } }
		 * 
		 * });
		 */

		// filter stuff
	}

	public int getFilterColumn() {
		return filterColumn;
	}

	public void setFilterColumn(int currentFilterColumn) {
		this.filterColumn = currentFilterColumn;
	}

	public int[] getCurrentFilterMapping() {
		return currentFilterMapping;
	}

	public void setCurrentFilterMapping(int[] currentFilterMapping) {
		this.currentFilterMapping = currentFilterMapping;
	}

	public int getCurrentFilterMatches() {
		return currentFilterMatches;
	}

	public void setCurrentFilterMatches(int currentFilterMatches) {
		this.currentFilterMatches = currentFilterMatches;
	}

	public String getFilter() {
		return filter;
	}

	final static String DEFAULT_FILTER = "^#.*";
	
	public void setFilter(String filter) {
		String tmpfilter = DEFAULT_FILTER.replace("#", filter);
		System.out.println("filter set:" + tmpfilter);
		this.filter = tmpfilter;
		doFilter();
		updateUI();
		//repaint();
	}

	public FilterableTableModel getFilterableTableModel() {
		return filterableTableModel;
	}

	public void setFilterableTableModel(
			FilterableTableModel filterableTableModel) {
		this.filterableTableModel = filterableTableModel;
	}

	private void doFilter() {
	//	System.out.println("dofilter ");
		currentFilterMatches = 0;
		TableModel model = super.getModel();
		int rowCount = model.getRowCount();
	//	System.out.println("model get:" + model);
	//	System.out.println("rc get:" + rowCount);
		int[] tmpMapping = new int[rowCount];

		for (int i = 0, j = 0; i < rowCount; i++) {
			if (model.getValueAt(i, filterColumn).toString().matches(
					this.filter)) {
				currentFilterMatches++;
				//System.out.println("match:" + j + ":" + i);
				tmpMapping[j++] = i;
			}
		}

		currentFilterMapping = new int[currentFilterMatches];
		System.arraycopy(tmpMapping, 0, currentFilterMapping, 0,
				currentFilterMatches);
		this.filterableTableModel.setFilterMapping(currentFilterMapping);
	}

	String oldfilter = "";

	public TableModel getModel() {
		TableModel tm = super.getModel();
		//System.out.println("model get:" + tm);
		//System.out.println("model get:" + filter);
		if (filter == null || filter.equals("")) {
			return tm;
			// return super.getModel();
		} else {
			if (filterableTableModel == null) {
				doFilter();
				setEditingRow(0);
			}
			return filterableTableModel;
		}
	}

	public TableRowSorter<PermTableModel> getSorter() {
		return sorter;
	}

	protected JTableHeader createDefaultTableHeader() {
		return new JTableHeader(columnModel) {
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			public String getToolTipText(MouseEvent e) {
				java.awt.Point p = e.getPoint();
				int index = columnModel.getColumnIndexAtX(p.x);
				int realIndex = columnModel.getColumn(index).getModelIndex();

				return strTooltips[realIndex];
			}
		};
	}
}
